package jgl.vajra.operator.widget.utils;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.TextUtils;

import jgl.vajra.operator.BuildConfig;
import jgl.vajra.operator.constant.Constant;
import jgl.vajra.operator.widget.permissions.PermissionsUtil;
import jgl.vajra.operator.widget.retrofithelper.rxschedulers.RxSchedulersHelper;
import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.text.DecimalFormat;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.FragmentActivity;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import okhttp3.MediaType;

/**
 * @Author zhangshuqi
 * @CreateTime 2018/3/27
 * @Describe
 */

public class FileUtils {


    private static String APP_CACHE_DIR = "";

    @NonNull
    public static String getStoragePath() {
        return Environment.getExternalStorageDirectory().getPath();
    }


    public static String DISK_CACHE_PATH = getDiskCacheDir() + "/vajra/cache";

    public static String FILE_PATH = "/vajra/data/file";
    public static String APK_PATH = "/vajra/data/apk";
    public static String CACHE_PATH = "/vajra/data/cache";
    public static String IMAGE_PATH = "/vajra/data/img";
    public static String VIDEO_PATH = "/vajra/data/video";
    public static String EXCEPTION_PATH = "/vajra/data/exception";

    public static File getImageFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getImageFolderFilePath();
        if (diskCacheDir == null) return null;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    @Nullable
    public static String getImageFolderFilePath() {
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + IMAGE_PATH;
        return diskCacheDir;
    }

    @Nullable
    public static String getVideoFolderFilePath() {
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + VIDEO_PATH;
        return diskCacheDir;
    }

    public static File getExceptionFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + EXCEPTION_PATH;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static File getFileFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + FILE_PATH;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static String getImageFolderPath() {
        File imageFolderFile = getImageFolderFile();
        if (imageFolderFile == null) return "";
        return imageFolderFile.getAbsolutePath();
    }

    public static File getNetCacheFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + CACHE_PATH;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static File getVideoFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getStoragePath();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + "/vajra";
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static File getApkFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + APK_PATH;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static File getApkFilePath(String fileName) {
        return new File(getApkFolderFile(), fileName);
    }

    public static File getDiskNetCacheFolderFile() {
        if (!hasSdcard())
            return null;
        String diskCacheDir = getDiskCacheDir();

        if (TextUtils.isEmpty(diskCacheDir)) {
            return null;
        }
        diskCacheDir = diskCacheDir + CACHE_PATH;
        File dirFile = new File(diskCacheDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return dirFile;
    }

    public static File saveImageFile(final File fromFile, final String toFileName) {
        File imageFolderPath = getImageFolderFile();
        if (imageFolderPath == null) return null;
        File toFile = new File(imageFolderPath, toFileName);
        if (!toFile.exists()) {
            try {
                int byteread = 0;
                toFile.createNewFile();
                InputStream inStream = new FileInputStream(fromFile); //读入原文件
                FileOutputStream fs = new FileOutputStream(toFile);
                byte[] buffer = new byte[1024];
                while ((byteread = inStream.read(buffer)) != -1) {
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return toFile;
    }

    public static void saveFile(final File file, final String fileName, final FragmentActivity activity) {
        if (!file.exists()) {
            return;
        }
        io.reactivex.Observable.create(new ObservableOnSubscribe<File>() {
            @Override
            public void subscribe(ObservableEmitter<File> emitter) throws Exception {
                File imageFolderPath = getFileFolderFile();
                if (imageFolderPath == null) emitter.onError(new NullPointerException());
                File copyFile = new File(imageFolderPath, fileName);
                if (!copyFile.exists()) {
                    try {
                        int byteread = 0;
                        copyFile.createNewFile();
                        InputStream inStream = new FileInputStream(file); //读入原文件
                        FileOutputStream fs = new FileOutputStream(copyFile);
                        byte[] buffer = new byte[1024];
                        while ((byteread = inStream.read(buffer)) != -1) {
                            fs.write(buffer, 0, byteread);
                        }
                        inStream.close();
                        emitter.onNext(copyFile);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    emitter.onNext(copyFile);
                }
            }
        }).compose(RxSchedulersHelper.<File>applyIoTransformer()).subscribe(new Observer<File>() {


            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(File file) {
                ToastUtils.showShort("已保存图片至" + file.getAbsolutePath());
                ImageUitls.savePicRefreshGallery(activity, file);
            }
        });


    }

    public static Uri setFilePermission(File mVideoFile) {
        Uri fileUri = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //针对Android7.0，需要通过FileProvider封装过的路径，提供给外部调用
            fileUri = FileProvider.getUriForFile(UIUtils.getContext(), UIUtils.getContext()
                            .getPackageName() + ".fileProvider",
                    mVideoFile);//通过FileProvider创建一个content类型的Uri，进行封装
        } else { //7.0以下，如果直接拿到相机返回的intent值，拿到的则是拍照的原图大小，很容易发生OOM
            // ，所以我们同样将返回的地址，保存到指定路径，返回到Activity时，去指定路径获取，压缩图片
            fileUri = Uri.fromFile(mVideoFile);
        }
        return fileUri;
    }


    public static boolean hasSdcard() {
        return Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);
    }

    /**
     * @Description: 打开系统文件管理器
     * @Author: niebin
     * @Date: 2018/3/20 下午4:20
     */
    public static void openFileExplorer(Activity from, String title) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        from.startActivityForResult(Intent.createChooser(intent, title), Constant.GET_FILE_SYSTEM);
    }


    public static void deleteFile(File file) {
        if (file == null) return;
        if (file.isFile() || file.exists()) {
            file.delete();
        }
    }

    /**
     * @Description: 根据Uri获取File
     * @Author: niebin
     * @Date: 2018/3/23 下午12:11
     */
    public static File getFileFromUri(Context context, Uri uri) {
        if (uri == null) {
            ToastUtils.showShort("未知错误");
        }
        File file = null;
        String filePath = getFileData(context, uri);
        if (isImage(filePath) || isUnloadFileType(filePath)) {
            file = new File(filePath);
        } else {
            ToastUtils.showShort("该文件不符合文件上传类型");
        }
        return file;
    }

    /***
     *
     * @param path
     * @return 返回是文件还是图片类型
     */
    public static boolean isImage(String path) {
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        path = path.toLowerCase();
        return path.endsWith(".jpeg") || path.endsWith(".jpg") || path.endsWith(".gif") || path
                .endsWith(".tif") || path.endsWith(".png");
    }

    /***
     *
     * @param path
     * @return 返回是否文件是上传要求格式类型
     */
    public static boolean isUnloadFileType(String path) {
        path = path.toLowerCase();
        if (path.endsWith(".txt") || path.endsWith(".doc") || path.endsWith(".docx") || path
                .endsWith(".ppt") || path.endsWith(".pptx") || path.endsWith(".jpg") || path
                .endsWith(".gif") || path.endsWith(".xls") || path.endsWith(".rar") || path
                .endsWith(".sql") || path.endsWith(".zip") || path.endsWith(".tif") || path
                .endsWith(".pdf") || path.endsWith(".xlsx") || path.endsWith(".mp4") || path
                .endsWith(".mp3")) {
            return true;
        } else if (isVideoFile(path)) {
            return true;
        } else if (isRecordFile(path)) {
            return true;
        }
        return false;
    }

    public static boolean isVideoFile(String path) {
        File file = isFileAndExists(path);
        if (file == null) {
            return false;
        }
        path = file.getName();
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        path = path.toLowerCase();

        return path.endsWith(".mp4") || path.endsWith(".m4v") || path.endsWith(".3gp") || path
                .endsWith(".3gpp") || path.endsWith(".3g2") || path.endsWith(".wmv");
    }

    public static File isFileAndExists(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }

        File file = new File(path);
        if (file.exists() && file.isFile()) {
            return file;
        }

        return null;
    }

    public static boolean isRecordFile(String path) {
        File file = isFileAndExists(path);
        if (file == null) {
            return false;
        }

        path = file.getName();
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        path = path.toLowerCase();
        return path.endsWith(".mp3") || path.endsWith(".m4a") || path.endsWith(".wav") || path
                .endsWith(".amr") || path.endsWith(".awb") || path.endsWith(".wma");
    }

    public static String getFileData(Context context, Uri uri) {
        if ((PhoneUtils.PHONE_BRAND_HUAWEI.equals(PhoneUtils.getPhoneBrand()) || PhoneUtils
                .PHONE_BRAND_HONOR.equals(PhoneUtils.getPhoneBrand())) && uri.toString()
                .contains("content://com.huawei.hidisk.fileprovider/root")) {
            String path = uri.toString().replace("content", "file").replace("com.huawei.hidisk" +
                    ".fileprovider/root", "");
            uri = Uri.parse(path);
        }

        if ("file".equalsIgnoreCase(uri.getScheme())) {
            //使用第三方应用打开
            return uri.getPath();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //4.4以后
            return getPath(context, uri);

        } else {
            //4.4以下下系统调用方法
            return getRealPathFromURI(context, uri);
        }

    }

    /**
     * 从Android系统4.4版本开始，选取相册中的的图片不再返回图片真实的Uri了，而是一个封装过的Uri，
     * 因此如果是4.4版本及以上的手机就需要对这个Uri进行解析才行。
     */
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        if (DocumentsContract.isDocumentUri(context, uri)) {
            if (isExternalStorageDocument(uri)) {
                // ExternalStorageProvider
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            } else if (isDownloadsDocument(uri)) {
                // DownloadsProvider
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            } else if (isMediaDocument(uri)) {
                // MediaProvider
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // MediaStore (and general)
            return getDataColumn(context, uri, null, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            // File
            return uri.getPath();
        }
        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    public static String getRealPathFromURI(Context context, Uri contentUri) {
        String res = null;
        String[] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
        if (null != cursor && cursor.moveToFirst()) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            res = cursor.getString(column_index);
            cursor.close();
        }
        return res;
    }

    public static MediaType guessMimeType(String fileName) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        fileName = fileName.replace("#", "");
        String contentType = fileNameMap.getContentTypeFor(fileName);
        return contentType == null ? MediaType.parse("application/octet-stream") : MediaType.parse(contentType);
    }

    public static String getDiskCacheDir() {
        if (TextUtils.isEmpty(APP_CACHE_DIR)) {
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                    || !Environment.isExternalStorageRemovable()) {
                APP_CACHE_DIR = Environment.getExternalStorageDirectory() + "/Android/data/"
                        + BuildConfig.APPLICATION_ID + "/cache";
                File file = new File(APP_CACHE_DIR);
                if (!file.exists()) {
                    boolean isMake = file.mkdirs();
                    // 创建失败再用系统方式获取
                    if (!isMake) {
                        file = UIUtils.getContext().getExternalCacheDir();
                        if (file != null) {
                            APP_CACHE_DIR = file.getAbsolutePath();
                        }
                    }
                }
            } else {
                APP_CACHE_DIR = UIUtils.getContext().getCacheDir().getPath();
            }
        }

        return APP_CACHE_DIR;
    }
/*
    public static String getExternalFilesDir() {
        String cachePath = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            cachePath = UIUtils.getContext().getExternalFilesDir().getPath();
        } else {
            cachePath = UIUtils.getContext().getCacheDir().getPath();
        }
        return cachePath;
    }
*/

    public static void getFileIntent(Intent intent, File file) {
        Uri uri = Uri.parse("file://" + file.toString());
        if (Build.VERSION.SDK_INT >= 24) { //判读版本是否在7.0以上
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(UIUtils.getContext(), UIUtils.getContext().getPackageName() + ".fileprovider", file);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }

    }
    private static boolean deleteDir(File dir) {
        if (dir != null && dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        return dir.delete();
    }
    public static String getTotalCacheSize(Context context) {
        long cacheSize = 0;
        try {
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                cacheSize += getFolderSize(context.getExternalCacheDir());
                Logger.d("cacheSize 1 ---" + cacheSize);
                cacheSize += getFolderSize(new File(FileUtils.getDiskCacheDir()));
                Logger.d("cacheSize 2 ---" + cacheSize);

                if (PermissionsUtil.hasPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    cacheSize += getFolderSize(new File(FileUtils.getStoragePath()));
                    Logger.d("cacheSize 3 ---" + cacheSize);
                }




            }
            return getFormatSize(cacheSize);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "0M";

    }
    public  static  String getFormatSize(double size) {
        double kiloByte = size / 1024;
        if (kiloByte < 1) {
            return "0.00M";
        }
        kiloByte = size / 1024 / 1024;
        BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
        return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
                .toPlainString() + "M";

    }
    public  static  long getFolderSize(File file)   {
        long size = 0;
        try {
            File[] fileList = file.listFiles();
            if (fileList != null) {
                for (int i = 0; i < fileList.length; i++) {
                    // 如果下面还有文件
                    if (fileList[i].isDirectory()) {
                        Logger.d("FolderDirectory"+fileList[i].getName());
                        size = size + getFolderSize(fileList[i]);
                    } else {
                        Logger.d("FolderFile"+fileList[i].getName()+"-------"+fileList[i].length());
                        size = size + fileList[i].length();
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return size;
    }



    public  static  void clearAllCache(Context context) {

        deleteDir(context.getCacheDir());
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            deleteDir(context.getExternalCacheDir());
            deleteDir(new File(FileUtils.getDiskCacheDir()));
            deleteDir( FileUtils.getImageFolderFile() );
        }
    }


    public static String getFormetFileSize(long size) {
        DecimalFormat df = new DecimalFormat("#.0");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (size == 0) {
            return wrongSize;
        }
        if (size < 1024) {
            fileSizeString = df.format((double) size) + "B";
        } else if (size < 1048576) {
            fileSizeString = df.format((double) size / 1024) + "KB";
        } else if (size < 1073741824) {
            fileSizeString = df.format((double) size / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) size / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    public static String getExtension(final String filename) {
        if (filename == null) {
            return null;
        }
        final int index = filename.lastIndexOf(".");
        if (index < 0) {
            return "";
        } else {
            return   filename.substring(index + 1);
        }
    }
}
